package LocalFlowMonitor.app;

import java.io.*;
import java.net.InetAddress;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

import jpcap.*;
import jpcap.packet.*;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NetFetcher implements PacketReceiver {

    private static final Logger logger = LoggerFactory.getLogger(NetFetcher.class);
    // 流量计数bytes
    private static double flows = 0.0;
    private static final DecimalFormat df = new DecimalFormat("0.00");

    private static int receivePacketTimes = 0;

    private static double lossPacketTimes = 0.0;

    private static Long preSeq = 0L;
    private static InetAddress preSrc = null;
    private static InetAddress preDst = null;

    @Override
    public void receivePacket(Packet arg0) {
        TCPPacket tcp = (TCPPacket) arg0;
        flows += tcp.data.length;

        receivePacketTimes += 1;
        if (tcp.sequence <= preSeq && tcp.src_ip == preSrc && tcp.dst_ip == preDst) {
            lossPacketTimes += 1;
        }
        preSeq = tcp.sequence;
        preSrc = tcp.src_ip;
        preDst = tcp.dst_ip;

        double lossRate = lossPacketTimes / receivePacketTimes;

        if (receivePacketTimes % 1000 == 0) {
            String _currentFlowMsg = "\nRequest ip: " + tcp.src_ip + " ,target ip: " + tcp.dst_ip + "\nPacketSize: " + tcp.data.length + " bytes\n";
            if (flows < 1024) {
                _currentFlowMsg += "Total flows: " + flows + " bytes";
            } else if (flows > 1024 && flows < 1e+6) {
                _currentFlowMsg += "Total flows: " + df.format(flows / 1024) + " KB";
            } else if (flows > 1e+6 && flows < 1e+9) {
                _currentFlowMsg += "Total flows: " + df.format(flows / 1024 / 1024) + " MB";
            } else {
                _currentFlowMsg += "Total flows: " + df.format(flows / 1024 / 1024 / 1024) + " GB";
            }
            _currentFlowMsg += "\nLoss-rate: " + (int) (lossRate * 100) + "%";
            logger.info(_currentFlowMsg);

            try {
                setFlowonHtml(_currentFlowMsg);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }//输出

        if (receivePacketTimes > 100000) {
            receivePacketTimes = 0;
            lossPacketTimes = 0;
        }//防溢出处理
    }

    private void setFlowonHtml(String flowMsg) throws Exception {
        String htmlstart = "<html>\n" +
                " <head> \n" +
                "  <title>HTTP-Flv Test</title> \n" +
                " </head> \n" +
                " <script src=\"//cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js\" type=\"text/javascript\"></script> \n" +
                "  <script src=\"//cdnjs.cloudflare.com/ajax/libs/flv.js/1.5.0/flv.min.js\" type=\"text/javascript\"></script>\n";
        String htmlend = "\n</html>\n";
        Document doc = Jsoup.parse(new File("D:\\multimedia.html"), "utf-8");

        Element flowinfo = doc.body().getElementById("flowinfo");
        flowinfo.text(flowMsg);
        String newpage = doc.body().toString();
        try {
            PrintStream ps = new PrintStream(new FileOutputStream("D:\\multimedia.html"));
            ps.println(htmlstart + newpage + htmlend);
        } catch (FileNotFoundException e) {
            logger.info("Output Html file not found.");
            throw new RuntimeException(e);
        }
    }

    public static void startFetcher() {

        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd :HH:mm:ss");
        logger.info("Start time: " + dateFormat.format(date));

        //获得网卡设备列表
        NetworkInterface[] devices = JpcapCaptor.getDeviceList();
        if (devices.length == 0) {

            System.out.println("无网卡信息！");
            return;
        }
        //输出网卡信息
        for (int i = 0; i < devices.length; i++) {

            System.out.println("网卡" + i + "信息:" + devices[i].name);
            for (NetworkInterfaceAddress address : devices[i].addresses) {

                System.out.print(address.address + " ");
            }
            System.out.println("\n");
        }

        Scanner scan = new Scanner(System.in);
        System.out.println("请选择您要监听的网卡序号：");
        int index = scan.nextInt();

        //监听选中的网卡
        try {
            JpcapCaptor jpcapCaptor = JpcapCaptor.openDevice(devices[index], 2000, false, 20);
            jpcapCaptor.loopPacket(-1, new NetFetcher());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        NetFetcher.startFetcher();
    }
}
